import { Node } from 'cc';
import { NodeKeyBoardProcessor } from './NodeKeyBoardProcessor';
import { NoKeyEventNode } from './NoKeyEventNode';
import { KeyEventListener } from '../../core/GameInputListeners';
import { InputKeyCode, KeyEventType } from '../../core/InputConfig';
import GameInputEvent from '../../core/GameInputEvent';
import GameInputMgr from '../../core/GameInputMgr';
/**
 * 由下而上，深度遍历节点中的NodeKeyBoardProcessor组件，判定事件的触发情况。
 */
export default class KeyBoardMgr implements KeyEventListener {

    private static ins: KeyBoardMgr

    static instance() {
        if (!this.ins) {
            this.ins = new KeyBoardMgr();
        }
        return this.ins;
    }

    isBlockInput(): boolean {
        return true;
    }

    onKeyBoardPress(keyCode: InputKeyCode, event?: GameInputEvent): void {
        this.emit(KeyEventType.PRESS, keyCode, event)
    }

    onKeyBoardRelease(keyCode: InputKeyCode, event?: GameInputEvent): void {
        this.emit(KeyEventType.RELEASE, keyCode, event)
    }

    constructor() {
        GameInputMgr.instance().addKeyEventListener(this)
    }

    get isValid(): boolean {
        return true;
    }

    protected _root: Node = null;

    set root(r: Node) {
        this._root = r;

    }

    get root() {
        return this._root;
    }

    protected downNode: { [key: number]: KeyEventListener } = {};


    emit(type: KeyEventType, code: InputKeyCode, event: GameInputEvent) {
        // Debug.log('KeyEventMgr emit  type ============================ ', type, ' code ', code)
        if (this.root) {
            let temp = this.dispatchEvent(this.root, type, code, event)
            switch (type) {
                case KeyEventType.PRESS:
                    if (temp && temp.isValid) {
                        this.downNode[code] = temp;
                    } else {
                        // LogUtils.log(' 按下时未找到节点')
                    }
                    break;
                case KeyEventType.RELEASE:
                    if (!temp) {
                        // LogUtils.log(' 抬起时未找到节点')
                    }
                    let processor = this.downNode[code];
                    if (processor && processor.isValid) {
                        if (processor !== temp) {
                            // Debug.log('未被松开的监听者', processor, code, temp)
                            // LogUtils.log(' temp ', temp)
                            processor.onKeyBoardRelease(code, event)
                        } else {
                            this.downNode[code] = null;
                        }
                    }
                    break;
            }
        }
    }

    private dispatchEvent(root: Node, type: KeyEventType, keyCode: InputKeyCode, event: GameInputEvent): KeyEventListener {
        if (!root || !root.parent || !root.active || root.getComponent(NoKeyEventNode)) {
            return null;
        }
        let temp: KeyEventListener = null;

        let count = root.children.length
        for (let index = count - 1; index >= 0; index--) {
            const element = root.children[index];
            temp = this.dispatchEvent(element, type, keyCode, event)
            if (temp) {
                break;
            }
        }
        if (!temp) {
            // LogUtils.log('dispatchEvent NodeKeyBoardProcessor', NodeKeyBoardProcessor)
            let processor: NodeKeyBoardProcessor = root.getComponent(NodeKeyBoardProcessor) as NodeKeyBoardProcessor
            if (processor && processor.isActive) {
                switch (type) {
                    case KeyEventType.PRESS:
                        temp = processor.onKeyBoardPress(keyCode, event)
                        break;
                    case KeyEventType.RELEASE:
                        temp = processor.onKeyBoardRelease(keyCode, event)
                        break;
                }
            }
        }

        return temp;

    }
}